package edu.drexel.cs544.group11.common;

import java.io.IOException;
import java.io.PrintStream;

/**
 * Represents a request message in the BSP.
 * 
 * CS 544
 * 
 * @author Group 11:
 * @author Jason Setzer
 * @author Tam Thongsima
 * @author Kenny Oyefara
 * @author Chase Miller
 * 
 * @date Spring 2013
 * 
 */
public class RequestMessage extends MessageBase {
    
    private RequestCommand command;
    private int messageSeqId;
    private double version;
    private String sessionId;
    private String messageBody;
    
    /**
     * Create an object when you have the message. This is useful when creating
     * a request message on the client. All properties of this object should be
     * defined within the constructor
     * 
     * @param command
     * @param messageSeqId
     * @param messageBody
     */
    public RequestMessage(RequestCommand command, int messageSeqId, double version, String messageBody) {
	this.command = command;
	this.messageSeqId = messageSeqId;
	this.messageBody = messageBody;
	this.version = version;
    }
    
    public RequestMessage(RequestCommand command, int messageSeqId, double version) {
	this(command, messageSeqId, version, null);
    }
    
    /**
     * Create a RequestMessage object from a string. This is useful when getting
     * text from the client.
     * 
     * @param messageAsText
     * 
     * @throws - If the text cannot be parsed, a MessageFormatException will be
     *         thrown.
     */
    public RequestMessage(String messageAsText) throws MessageFormatException {
	String lines[] = messageAsText.split(super.separator);
	
	for (int i = 0; i < lines.length; i++) {
	    lines[i] = lines[i].trim();
	}
	
	try {
	    String commandAsString = lines[0];
	    String seqIdAsString = lines[1];
	    Double version = Double.parseDouble(lines[2]);
	    String message = lines[3];
	    
	    this.command = RequestCommand.valueOf(commandAsString);
	    this.messageSeqId = Integer.parseInt(seqIdAsString);
	    this.version = version;
	    this.messageBody = (message.equals(super.emptyIndicator)) ? null : message;
	}
	catch (Throwable t) {
	    throw new MessageFormatException("Could not parse message string into RequestMessage object: " + messageAsText, t);
	}
    }
    
    /**
     * Sends this message to the specified print stream.
     * 
     * @param stream
     */
    @Override
    public void sendMessage(PrintStream stream) throws IOException, MessageFormatException {
	if (this.isMalformedMessage()) {
	    throw new MessageFormatException("This message is malformed and does not adhere to the PDU.");
	}
	else {
	    String text = this.formatForProtocolTransmission();
	    stream.write(text.getBytes());
	}
    }
    
    /**
     * Logic to detect if this message is malformed (i.e. is missing stuff we
     * defined in the PDU message seq id and a command)
     * 
     * @return
     */
    @Override
    public boolean isMalformedMessage() {
	boolean isMalformed = false;
	
	if (this.command == null) {
	    isMalformed = true;
	}
	
	return isMalformed;
    }
    
    /**
     * Formats this message for transmission over the network.
     */
    @Override
    public String formatForProtocolTransmission() {
	String formattedMessage = (this.messageBody == null) ? super.emptyIndicator : this.messageBody;
	formattedMessage = (formattedMessage.equals("")) ? super.emptyIndicator : formattedMessage;
	
	String finalString = this.command + super.separator + this.messageSeqId + super.separator + this.version + super.separator + formattedMessage + RequestMessage.getEndOfMessage();
	return finalString;
    }
    
    /**
     * Gets this message's command.
     * 
     * @return
     */
    public RequestCommand getCommand() {
	return this.command;
    }
    
    public double getVersion() {
	return this.version;
    }
    
    public String getSessionId() {
	return sessionId;
    }
    
    public void setSessionId(String sessionId) {
	this.sessionId = sessionId;
    }
    
    public int getMessageSeqId() {
	return messageSeqId;
    }
    
    public void setMessageSeqId(int messageSeqId) {
	this.messageSeqId = messageSeqId;
    }
    
    public void setCommand(RequestCommand command) {
	this.command = command;
    }
    
    public String getMessageBody() {
	return messageBody;
    }
    
    /**
     * Returns the characters representing the end of a request Message.
     * 
     * @return
     */
    public static String getEndOfMessage() {
	return MessageBase.getEndOfMessage();
    }
}